package com.cimp.service.iqy;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.cimp.dao.iqy.IqyVirtualDao;
import com.cimp.domain.iqy.MetaResultBean;
import com.cimp.domain.iqy.ResultBean;
import com.cimp.domain.iqy.ResultCode;
import com.cimp.domain.iqy.Virtual;
import com.cimp.domain.iqy.call.Call;
import com.cimp.domain.iqy.call.Period;
import com.cimp.service.iqy.interfaces.DataInterface;
import com.cimp.service.iqy.interfaces.GenerateInterface;
import com.cimp.util.iqy.CommonUtil;
import com.cimp.util.iqy.IqyContants;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

@Service
public class IqyService {

    @Resource
    private IqyVirtualDao iqyVirtualDao;

    @Resource
    private DataInterface dataInterface;

    @Resource
    private GenerateInterface generateInterface;

    private volatile boolean changeSupplementing;

    public String generateToken() {
        String token = CommonUtil.generateToken();
        return token;
    }

    public void insertVirtual(Virtual virtual) {
        iqyVirtualDao.insertVirtual(virtual);
    }

    public void updateVirtual(Virtual virtual) {
        iqyVirtualDao.updateVirtual(virtual);
    }

    public List<Virtual> queryVirtualInterface() {
        return iqyVirtualDao.listVirtual();
    }

    public void deleteVirtualInterface(Integer id) {
        iqyVirtualDao.deleteVirtual(id);
    }

    public void updateVirtualState(Virtual virtual) {
        iqyVirtualDao.updateVirtualState(virtual);
        if (IqyContants.VIRTUAL_STATE_ACTIVE == virtual.getState()) {
            iqyVirtualDao.inActiveOtherVirtualState(virtual);
        }
    }

    public String queryVirtualContent(String region) {
        return iqyVirtualDao.queryVirtualContent(region);
    }

    /**
     * 爱奇艺接口调用
     */
    public String callInterface(Call call) throws JsonProcessingException {
        String result = null;
        ResultBean resultBean = null;
        MetaResultBean metaResultBean = null;
        String url = IqyContants.interfaceMap.get(call.getName());
        switch (call.getName()) {
            case "chn-list":
                resultBean = generateInterface.queryChannelList(url);
                break;
            case "metas-info":
                metaResultBean = generateInterface.queryMetaInfo(url, call.getId());
                break;
            case "ep-list":
                resultBean = generateInterface.queryVideoList(url, call.getId(), call.getStype(), call.getEpType()
                        , call.getPn(), call.getPs());
                break;
            case "people":
                metaResultBean = generateInterface.queryPeopleInfo(url, call.getId());
                break;
            case "switch":
                break;
            case "hot-count":
                break;
            case "snapshot":
                resultBean = dataInterface.queryChannelSnapshot(url, call.getChnId(), call.getType());
                break;
            case "change":
                resultBean = dataInterface.queryContentChange(url, call.getStartTs(), call.getEndTs(), call.getType()
                        , call.getPn(), call.getLastId());
                break;
            case "change-supplement":
                resultBean = callChangeSupplement(call, url);
                break;
            case "people-snapshot":
                resultBean = dataInterface.queryPeopleSnapshot(url);
                break;
            case "people-change":
                resultBean = dataInterface.queryPeopleChange(url, call.getStartTs(), call.getEndTs()
                        , call.getPn(), call.getLastId());
                break;
            default:
                throw new RuntimeException("Not supported by the interface type");

        }
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        if (resultBean != null) {
            return objectMapper.writeValueAsString(resultBean);
        }
        if (metaResultBean != null) {
            return objectMapper.writeValueAsString(metaResultBean);
        }
        return null;
    }

    private ResultBean<Long> callChangeSupplement(Call call, String url) {
        List<Period> periods = new ArrayList<>();
        Integer subTime = call.getEndTs() - call.getStartTs();
        if (subTime <= 3600) {
            periods.add(new Period(call.getStartTs(), call.getEndTs()));
        } else {
            Integer tempStart = call.getStartTs();
            Integer tempEnd = null;
            for (int i = 0; i <= subTime / 3600; i++) {
                tempEnd = tempStart + 3600;
                if (tempEnd > call.getEndTs()) {
                    periods.add(new Period(tempStart, call.getEndTs()));
                } else {
                    periods.add(new Period(tempStart, tempEnd));
                }
                tempStart = tempEnd;
            }
        }

        ResultBean<Long> resultBean = new ResultBean<>();
        resultBean.setCode("C00000");
        if (changeSupplementing) {
            resultBean.setCode("change supplementing");
            return resultBean;
        }
        changeSupplementing = true;
        Set<Long> contentChangeList = new HashSet<>();
        try {
            for (Period period : periods) {
                LocalDateTime startDateTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(period.getStartTs()), ZoneId.systemDefault());
                LocalDateTime endDateTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(period.getEndTs()), ZoneId.systemDefault());
                System.out.println(startDateTime + " " + endDateTime);
                this.queryContentChange(url, contentChangeList, period.getStartTs(), period.getEndTs(), call.getType(), 1, 0L);
            }
            List<Long> list = new ArrayList<>(contentChangeList);
            resultBean.setData(list);
            resultBean.setTotal(list.size());
        } catch (Exception e) {
            resultBean.setCode("C00007");
            e.printStackTrace();
        }
        changeSupplementing = false;
        return resultBean;
    }

    /**
     * 递归查询增量ID列表
     */
    private void queryContentChange(String url, Set<Long> contentChangeList, int startTs, int endTs, int type,
                                    int pn, long lastId) {
        Set<Long> changeList = new HashSet<>();
        List<Long> contentChange = null;
        try {
            //接口调用
            DataInterface dataInterface = new DataInterface();
            ResultBean<Long> resultBean = dataInterface.queryContentChange(url, startTs, endTs, type, pn, lastId);
            Thread.sleep(2000);
            if (!ResultCode.isSuccess(resultBean.getCode())) {
//                DEBUGLOG.error(ResultCode.getResultMsg(resultBean.getCode()));
                throw new RuntimeException("interface error: " + ResultCode.getResultMsg(resultBean.getCode()));
            }
            //处理逻辑
            contentChange = resultBean.getData();
            contentChangeList.addAll(contentChange);
            //下一页
            int ps = resultBean.getPs();

            if (ps != 0 && pn * ps < resultBean.getTotal()) {
                this.queryContentChange(url, contentChangeList, startTs, endTs, type, ++pn
                        , contentChange.get(contentChange.size() - 1));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
